package _untouchable_;


import java.util.*;


/**
 * In der Klasse {@link Schedule} sind die Schedule-Eintr&auml;ge ({@link SSI}) organisiert.
 * {@link Schedule} implementiert das {@link java.util.Iterator}<({@link SSI})>-Interface.
 */
public class Schedule implements Iterator<SSI> {
    
    /**
     * Zun&auml;chst: Sie haben <u>nicht</u> die Zeit dies zu lesen ;-)<br />
     * {@link #schedule} ist der eigentliche Schedule.
     */
    private final SSI[] schedule;                                               // the schedule
    
    
    /**
     * Zun&auml;chst: Sie haben <u>nicht</u> die Zeit dies zu lesen ;-)<br />
     * {@link #currentStopIndex} ist der interne Index zum Durchlaufen der Elemente des internen {@link #schedule}.
     */
    private int currentStopIndex;                                               // Current Stop (Index in schedule)                      
    
    
    
    
    
    /**
     * Zun&auml;chst: Sie haben <u>nicht</u> die Zeit dies zu lesen ;-)<br />
     * Der Konstruktor erzeugt den (internen) eigentlichen {@link #schedule} und setzt den internen {@link #currentStopIndex}.
     * Zwei unmittelbar aufeinanderfolgende Stationen unterscheiden sich (mindestens) bez&uuml;glich Ihrer Position.
     */
    public Schedule(){
        int minDuration      =  Config.getMinDuration();
        int maxDuration      =  Config.getMaxDuration();
        int numberOfTargets  =  Config.getNumberOfLandings();
        int numberOfStops    =  ( Config.getNumberOfStops() > 0 )  ?  Config.getNumberOfStops()  :  3 + (int)( 30*Math.random() );
        int startPosition    =  (int)( Config.getNumberOfLandings()*Math.random() );
        
        int factor = 1 + maxDuration - minDuration;                             // internal factor (for computation of duration time)
        // check parameter
        if ( factor < 0 ){
            System.out.println( "Think twice about your parameter values for min and/or max duration - max duration must not be smaller than min duration" );
            System.out.flush();
            factor = 0;
        }//if
        
        if ( numberOfStops < 1 ){
            System.out.println( "Think twice about your parameter values for numberOfStops - number of stops must be at least one" );
            System.out.flush();
            numberOfStops = 3;
        }//if
        
        assert numberOfTargets >= 2 || numberOfTargets >= numberOfStops : "number of targets is unreasonable";
        if ( numberOfTargets < 2 && numberOfTargets < numberOfStops ){
            System.out.println( "Think twice about your parameter values for number of targets(harbours)" );
            System.out.flush();
            numberOfTargets = 3;
        }//if        
        
        schedule = new SSI[numberOfStops];
        int workIndex = numberOfStops-1;
        int stopPosition = startPosition;
        int durationTimeAtStop = minDuration + (int)( factor * Math.random() );
        schedule[workIndex] = new SSI( stopPosition, durationTimeAtStop );
        
        while ( workIndex > 0 ){
            stopPosition = ( stopPosition + 1 + (int)( (numberOfTargets-1) * Math.random() ) ) % numberOfTargets;
            durationTimeAtStop = minDuration + (int)( factor * Math.random() );            
            schedule[--workIndex] = new SSI( stopPosition, durationTimeAtStop );
        }//while
        
        currentStopIndex = numberOfStops;
    }//Schedule
    
    
    
    
    
    /**
     * {@link #hasNext()} tut was {@link java.util.Iterator#hasNext()} tun muss &rarr; siehe 1.Semester {@link java.util.Iterator}.
     * Denken Sie daran, die Klasse {@link Schedule} implementiert {@link java.util.Iterator Iterator}<{@link SSI}>.
     * @return <code>true</code> wenn noch Elemente in der Iteration sind.<br />
     * (Mit anderen Worten, es wird <code>true</code> abgeliefert, wenn {@link #next()} eine Element abliefern
     * und keine Exception werfen w&uuml;rde.) 
     */
    public boolean hasNext(){ return currentStopIndex > 0; }
    
    
    /**
     * {@link #next()} tut was {@link java.util.Iterator#next()} tun muss &rarr; siehe 1.Semester {@link java.util.Iterator}.
     * Denken Sie daran, die Klasse {@link Schedule} implementiert {@link java.util.Iterator Iterator}<{@link SSI}>.
     * @return das n&auml;chste Element in der Iteration.
     * @throws NoSuchElementException wenn kein Element (mehr) in der Iteration vorhanden ist.
     */
    public SSI next(){
        if ( this.hasNext() ){
            return schedule[ --currentStopIndex ];
        }else{
            throw new NoSuchElementException();
        }//if
    }//next
    
    
    /**
     * {@link #remove()} wird nicht unterst&uuml;tzt.
     * @throws UnsupportedOperationException bei jedem Auruf (da {@link #remove()} <u>nicht</u> unterst&uuml;tzt wird).
     */
    public void remove(){ throw new UnsupportedOperationException(); }
    
}//Schedule
